/**@file
   WDF driver helper class.
   
   @par license 
   Copyright 2012 Lu, Ken. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 
   @author: Lu, Ken (bluewish.ken.lu@gmail.com)
**/

#ifndef _USER_WDF_HELPER_H_
#define _USER_WDF_HELPER_H_

#include <Windows.h>
#include <stdint.h>
#include <string>

using namespace std;

namespace ken {

class WdfDriverHelper {
    enum STATUS {
        SUCCESS,
        NEED_REBOOT
    } ;

    typedef
    ULONG
    (WINAPI *PFN_WDFPREDEVICEINSTALL)(
        __in LPCWSTR  InfPath,
        __in_opt LPCWSTR  InfSectionName
        );

    typedef
    ULONG
    (WINAPI *PFN_WDFPOSTDEVICEINSTALL)(
        __in LPCWSTR  InfPath,
        __in_opt LPCWSTR  InfSectionName
        );

    typedef
    ULONG
    (WINAPI *PFN_WDFPREDEVICEREMOVE)(
        __in LPCWSTR  InfPath,
        __in_opt LPCWSTR  InfSectionName
        );

    typedef
    ULONG
    (WINAPI *PFN_WDFPOSTDEVICEREMOVE)(
        __in LPCWSTR  InfPath,
        __in_opt LPCWSTR  InfSectionName
        );

public:
    
    ~WdfDriverHelper(void);
    WdfDriverHelper(const wchar_t *device_name, const wchar_t* driver_name);
    void Initialize();
    void Install(const wchar_t* driver_dir, const wchar_t* inf_name, const wchar_t* inf_wdf_section_name);
    void Remove(const wchar_t* driver_dir, const wchar_t* inf_name, const wchar_t* inf_wdf_section_name);
    void Start();
    void Stop();
    uint8_t* u2a(const uint16_t *src, uint8_t *target);

private:
    WdfDriverHelper(void);
    HMODULE                     hCoInstallerDll_;
    std::wstring                device_name_;
    std::wstring                driver_name_;
    std::wstring                driver_dir_;
    PFN_WDFPREDEVICEINSTALL     pfn_WdfPreDeviceInstall_;
    PFN_WDFPOSTDEVICEINSTALL    pfn_WdfPostDeviceInstall_;
    PFN_WDFPREDEVICEREMOVE      pfn_WdfPreDeviceRemove_;
    PFN_WDFPOSTDEVICEREMOVE     pfn_WdfPostDeviceRemove_;

    std::wstring getCoInstallerDllName();
    bool checkFileExist(std::wstring& file_path);
    inline void reportWindowsError(const char* err);
    std::wstring getDriverFilePath(const wchar_t* driver_path);
    std::wstring getInfFilePath(const wchar_t *driver_path, const wchar_t *inf_name);

private:
    static uint16_t version_major_;
    static uint16_t version_minor_;
    static void SetVersion(uint16_t major, uint16_t minor);
};

}

#endif // _USER_WDF_HELPER_H_